#include "mystdio.h"
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#define DFL_MODE 0666

myFILE *my_fopen(const char *path, const char *mode)
{
    int fd = 0;
    int flag = 0;

    if(strcmp(mode, "r") == 0)
    {
        flag |= O_RDONLY;
    }
    else if(strcmp(mode, "w") == 0)
    {
        flag |= O_CREAT | O_TRUNC | O_WRONLY;
    }
    else if(strcmp(mode, "a") == 0)
    {
        flag |= O_CREAT | O_APPEND | O_WRONLY;
    }
    else{
        //do nothing
    }
    
    if(flag & O_CREAT)
    {
        fd = open(path, flag, DFL_MODE);
    }
    else{
        fd = open(path, flag);
    }

    if(fd < 0)
    {
        errno = 2;
        return NULL;
    }
    
    myFILE *fp = (myFILE*)malloc(sizeof(myFILE));
    if(fp == NULL)
    {
        errno = 3;
        return NULL;
    }
    fp->flag = FLUSH_LINE;
    fp->end = 0;
    fp->fileno = fd;

    return fp;
}

int my_fwrite(const char *s, int num, myFILE *stream)
{
    memcpy(stream->buf + stream->end, s, num);
    stream->end += num;
    
    int i = 0;

    for (i = 0; i < stream->end; i++)
    {
        if (stream->buf[i] == '\n' && stream->buf[i+1] != '\0')
        {
            int j = 0;
            for (j = i; j < stream->end; j++)
            {
                stream->buf[j] = stream->buf[j + 1];
            }
            i--;
            stream->end--;

            stream->buf[stream->end] = '\0';
        }
    }

    if(stream->end > 0 && (stream->flag & FLUSH_LINE) && stream->buf[stream->end-1] == '\n')
    {
        my_fflush(stream);
    }

    // 判断是否需要刷新 // "abcd\nefg"
    // if(stream->end > 0 && (stream->flag & FLUSH_LINE) && stream->buf[stream->end-1] == '\n')
    //{
    //    my_fflush(stream);
    //}
    return 0;
}

int my_fflush(myFILE *stream)
{
    if(stream->end > 0)
    {
        write(stream->fileno, stream->buf, stream->end);
        stream->end = 0;
    }
    return 0;
}

int my_fclose(myFILE *stream)
{
    my_fflush(stream); 
    return close(stream->fileno);
}
